package com.wocai.jrt.orgadmin.key;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.crypto.Cipher;

import org.junit.Test;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class KeyUtils {

	/** 指定加密算法为RSA */
	private static final String ALGORITHM = "RSA";
	/** 密钥长度，用来初始化 */
	private static final int KEYSIZE = 1024;
	/** 指定公钥存放文件 */
	private static String PUBLIC_KEY_FILE = "PUBLIC_KEY_FILE";
	/** 指定私钥存放文件 */
	private static String PRIVATE_KEY_FILE = "PRIVATE_KEY_FILE";

	private static final KeyUtils keyUtils = new KeyUtils();

	private KeyUtils() {
	}

	// 静态工厂方法
	public static KeyUtils getKeyUtils() {
		return keyUtils;
	}

	/**
	 * @Title: getKey
	 * @Description: 根据 keyFile 获取公钥 私钥
	 * @Time:2016年4月19日 下午3:31:57
	 * @param keyFile
	 * @return Key 返回类型
	 * @throws Exception
	 */
	public static Key getKey(String keyFile) throws Exception {
		generateKeyPair();
		Key key;
		ObjectInputStream ois = null;
		try {

			if (keyFile.endsWith(PUBLIC_KEY_FILE)) {
				/** 读取公钥对象 */
				ois = new ObjectInputStream(
						new FileInputStream(PUBLIC_KEY_FILE));
			} else if (keyFile.endsWith(PRIVATE_KEY_FILE)) {
				/** 读取私钥对象 */
				ois = new ObjectInputStream(new FileInputStream(
						PRIVATE_KEY_FILE));
			}
			key = (Key) ois.readObject();
		} catch (Exception e) {
			throw e;
		} finally {
			ois.close();
		}

		return key;
	}

	/**
	 * @Title: encrypt
	 * @Description: 根据 服务器硬件码、过期日期、员工数量、公钥 获取序列号
	 * @Time:2016年4月19日 下午3:12:54
	 * @param PCID
	 *            服务器硬件码
	 * @param date
	 *            过期日期
	 * @param employeeNum
	 *            员工数量
	 * @param publicKey
	 *            公钥
	 * @return String 返回类型 密文
	 * @throws Exception
	 */
	public static String encrypt(String PCID, Date date, int employeeNum,
			Key publicKey) throws Exception {
		String source = PCID + "@"
				+ (new SimpleDateFormat("yyyy-MM-dd")).format(date) + "@"
				+ employeeNum;
		return encrypt(source, publicKey);
	}

	/**
	 * @Title: deleteFile
	 * @Description: 删除公钥私钥文件
	 * @Time:2016年4月19日 下午5:49:43 void 返回类型
	 */
	public static void deleteFile() {

	}

	/**
	 * @Title: decrypt
	 * @Description: 根据 序列号、硬件码、私钥 获取 到期日 与 员工人数<br/>序列号错误返回空
	 * @Time:2016年4月19日 下午3:38:15
	 * @param serialNum
	 *            序列号
	 * @param PCID
	 *            硬件码
	 * @param privateKey
	 *            私钥
	 * @return String 返回类型
	 * @throws Exception
	 */
	public static String decrypt(String serialNum, String PCID, Key privateKey)
			throws Exception {
		String source = decrypt(serialNum, privateKey);
		if (PCID.equals(source.split("@")[0])) {
			return source.split("@")[1] + "@" + source.split("@")[2];
		}
		return null;
	}

	/**
	 * 生成密钥对
	 * 
	 * @throws Exception
	 */
	private static void generateKeyPair() throws Exception {
		// 判断文件是否存在
		String filePath = System.getProperty("user.dir");
		File publicFile = new File(filePath + "/" + PUBLIC_KEY_FILE);
		File privateFile = new File(filePath + "/" + PRIVATE_KEY_FILE);
		if (!(publicFile.exists() && privateFile.exists())) {

			/** RSA算法要求有一个可信任的随机数源 */
			SecureRandom secureRandom = new SecureRandom();

			/** 为RSA算法创建一个KeyPairGenerator对象 */
			KeyPairGenerator keyPairGenerator = KeyPairGenerator
					.getInstance(ALGORITHM);

			/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
			keyPairGenerator.initialize(KEYSIZE, secureRandom);
			// keyPairGenerator.initialize(KEYSIZE);

			/** 生成密匙对 */
			KeyPair keyPair = keyPairGenerator.generateKeyPair();

			/** 得到公钥 */
			Key publicKey = keyPair.getPublic();

			/** 得到私钥 */
			Key privateKey = keyPair.getPrivate();

			ObjectOutputStream oos1 = null;
			ObjectOutputStream oos2 = null;
			try {
				/** 用对象流将生成的密钥写入文件 */
				oos1 = new ObjectOutputStream(new FileOutputStream(
						PUBLIC_KEY_FILE));
				oos2 = new ObjectOutputStream(new FileOutputStream(
						PRIVATE_KEY_FILE));
				oos1.writeObject(publicKey);
				oos2.writeObject(privateKey);
			} catch (Exception e) {
				throw e;
			} finally {
				oos1.close();
				oos2.close();
			}
		}
	}

	/**
	 * 加密方法
	 * 
	 * @param source
	 *            源数据
	 * @return
	 * @throws Exception
	 */
	private static String encrypt(String source, Key publicKey)
			throws Exception {
		/** 得到Cipher对象来实现对源数据的RSA加密 */
		Cipher cipher = Cipher.getInstance(ALGORITHM);
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] b = source.getBytes();

		/** 执行加密操作 */
		byte[] b1 = cipher.doFinal(b);
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encode(b1);
	}

	/**
	 * 解密算法
	 * 
	 * @param cryptograph
	 *            密文
	 * @return 解密结果
	 * @throws Exception
	 */
	private static String decrypt(String cryptograph, Key privateKey)
			throws Exception {
		/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
		Cipher cipher = Cipher.getInstance(ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] b1 = decoder.decodeBuffer(cryptograph);

		/** 执行解密操作 */
		byte[] b = cipher.doFinal(b1);
		return new String(b);
	}
}